package tools;

import symbols.Token;

/** 语法树 */
public class SyntaxTree {
    private int size = 0;// 节点数量
    private int leaf = 0;// 叶子节点数量 用于自适应宽度
    private int depth = 0;// 二叉树深度

    private Node<Token> root;// 语法树根节点

    public Node<Token> getRoot() {
        return root;
    }

    public int getSize() {
        return this.size;
    }

    public int getLeaf() {
        return this.leaf;
    }

    public int getDepth() {
        return this.depth;
    }

    /** 插入语法树 */
    public void put(Token o, int depth) {
        // 更新语法树信息
        this.size++;
        if (o.tag < 512) {
            this.leaf++;
        }
        this.depth = Math.max(this.depth, depth);
        // 开始插入
        Node<Token> newNode = new Node<>(o);
        if (root == null) {
            root = newNode;
        } else {
            Node<Token> current = root;
            current = current.getRightmostNode();
            for (int i = 0; i < depth; i++) {
                if (current.getLeftNode() == null) {
                    current.setLeftNode(newNode);
                    return;
                }
                current = current.getLeftNode();
                current = current.getRightmostNode();
            }
            current.setRightNode(newNode);
        }
    }

    private int height;
    private int width;
    private String[][] res;// 模拟像素
    private int maxY = 0;// 控制缩进

    @Override
    public String toString() {
        // 自适应大小
        height = depth * 2 + 1;
        width = leaf * 2 - 1;
        res = new String[height][width];
        // 变形像素初始化
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                res[i][j] = (j % 2 == 0) ? "          " : "  ";
            }
        }
        // 递归输出语法树
        write(root, 0, 0);
        // 拼接结果
        StringBuilder sb = new StringBuilder();
        for (String[] line : res) {
            for (String str : line) {
                sb.append(str);
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    /** 记录当前节点 */
    public void write(Node<Token> n, int x, int y) {
        if (n != null && x < height && y < width) {
            maxY = Math.max(maxY, y);
            res[x][y] = format(n);
            // 左儿子
            if (n.getLeftNode() != null) {
                res[x + 1][y] = "    |     ";
                write(n.getLeftNode(), x + 2, y);
            }
            // 右儿子
            if (n.getRightNode() != null) {
                for (int i = y + 1; i < maxY + 2; i++)
                    res[x][i] = (i % 2 == 0) ? "----------" : "--";
                write(n.getRightNode(), x, maxY + 2);
            }
        }
    }

    /** 居中补全宽度至10 */
    private String format(Node<Token> n) {
        StringBuilder sb = new StringBuilder("<" + n.getData().toString() + ">");
        if (sb.length() < 10) {
            int o = 10 - sb.length();
            for (int i = 0; i < (o + 1) / 2; i++) {
                sb.append(" ");
            }
            for (int i = 0; i < o / 2; i++) {
                sb.insert(0, " ");
            }
        }
        return sb.toString();
    }
}
